#ifndef NRF24L01_H_
#define NRF24L01_H_

#include "../spi/spi_conf.h"
#include "../interruption/interruption.h"
#include "../gpio/gpio.h"
#include "../leds/leds.h"
#include "nRF24L01P_Default.h"

#include <stdio.h>


#define TX_DELAY			10
#define TPECE2CSN_DELAY		4
#define RX_PLOAD_WIDTH 		1
#define TX_PLOAD_WIDTH 		1
#define BUFFER_SIZE			32
#define TX_COUNT			200000

#define TX_MODE				0x0e
#define RX_MODE				0x0f

//Define the commands for operate the nRF24L01P
#define READ_nRF_REG    	0x00  // Command for read register
#define WRITE_nRF_REG   	0x20  // Command for write register
#define RD_RX_PLOAD     	0x61  // Command for read Rx payload
#define WR_TX_PLOAD     	0xA0  // Command for write Tx payload
#define FLUSH_TX        	0xE1  // Command for flush Tx FIFO
#define FLUSH_RX        	0xE2  // Command for flush Rx FIFO
#define REUSE_TX_PL     	0xE3  // Command for reuse Tx payload
#define RD_RX_PL_WID   		0x60  // Command for read Rx payload
#define W_TX_PAYLOAD_NOACK	0xB0  // No Ack Command
#define NOP             	0xFF  // Reserve

//Define the register address for nRF24L01P
#define CONFIG          0x00  // Configurate the status of transceiver, mode of CRC and the replay of transceiver status
#define EN_AA           0x01  // Enable the auto-ack in all channels
#define EN_RXADDR       0x02  // Enable Rx Address
#define SETUP_AW        0x03  // Configurate the address width
#define SETUP_RETR      0x04  // Setup the retransmit
#define RF_CH           0x05  // Configurate the RF frequency
#define RF_SETUP        0x06  // Setup the rate of data, and transmit power
#define NRFRegSTATUS    0x07  // Status Register
#define OBSERVE_TX      0x08  // Observe Register
#define CD              0x09  // Carrier detect
#define FEATURE_REG		0x1D  // Feature Register
#define DYNPD_REG		0x1C  // Dynpd (Dynamic payload) Register

//CONFIG REGISTER Options
#define CONFIG_RX_DR_DISABLE_INTERRUPT 0x40
#define CONFIG_RX_DR_ENABLE_INTERRUPT 0x00
#define CONFIG_TX_DS_DISABLE_INTERRUPT 0x20
#define CONFIG_TX_DS_ENABLE_INTERRUPT 0x00
#define CONFIG_MAX_RT_DISABLE_INTERRUPT 0x10
#define CONFIG_MAX_RT_ENABLE_INTERRUPT 0x00
#define CONFIG_ENABLE_CRC 0x08
#define CONFIG_DISABLE_CRC 0x00
#define CONFIG_CRC_1_Byte 0x00
#define CONFIG_CRC_2_Byte 0x04
#define CONFIG_PWR_UP 0x02
#define CONFIG_PWR_DOWN 	0x00
#define CONFIG_PRX 		0x01
#define CONFIG_PTX		 0x00

//ENABLE AUTO-ACK REGISTER Options
#define EN_AA_P5 		0x20
#define EN_AA_P4 		0x10
#define EN_AA_P3 		0x08
#define EN_AA_P2 		0x04
#define EN_AA_P1 		0x02
#define EN_AA_P0 		0x01

//ENABLE PIPE REGISTER Options
#define ENRX_P5 		0x20
#define ENRX_P4 		0x10
#define ENRX_P3			0x08
#define ENRX_P2 		0x04
#define ENRX_P1 		0x02
#define ENRX_P0 		0x01

//SETUP_AW (ADDRESS WIDTH) REGISTER Options
#define AW_3_BYTES 		0x01
#define AW_4_BYTES 		0x02
#define AW_5_BYTES 		0x03

//RETRASMIT REGISTER Options
#define CONT_WAVE		0x80
#define PLL_LOCK 		0x10
#define RF_DR_1_MBPS	0x00
#define RF_DR_2_MBPS	0x08
#define RF_DR_250_KBPS	0x20
#define RF_POWER_0_DPM	0x03
#define RF_POWER_6_DPM	0x02
#define RF_POWER_12_DPM	0x01
#define RF_POWER_18_DPM	0x00

//STATUS REGISTER Options
#define RX_DR 			0x40
#define TX_DS 			0x20
#define MAX_RT 			0x10
#define RX_P0 			0x00
#define RX_P1 			0x02
#define RX_P2 			0x04
#define RX_P3 			0x05
#define RX_P4 			0x08
#define RX_P5 			0x0A
#define RX_FIFO_EMPTY 	0x0E
#define TX_FULL 		0x01


#define RX_ADDR_P0      0x0A  // Receive address of channel 0
#define RX_ADDR_P1      0x0B  // Receive address of channel 1
#define RX_ADDR_P2      0x0C  // Receive address of channel 2
#define RX_ADDR_P3      0x0D  // Receive address of channel 3
#define RX_ADDR_P4      0x0E  // Receive address of channel 4
#define RX_ADDR_P5      0x0F  // Receive address of channel 5
#define TX_ADDR         0x10  // Transmit address
#define RX_PW_P0        0x11  // Size of receive data in channel 0
#define RX_PW_P1        0x12  // Size of receive data in channel 1
#define RX_PW_P2        0x13  // Size of receive data in channel 2
#define RX_PW_P3        0x14  // Size of receive data in channel 3
#define RX_PW_P4        0x15  // Size of receive data in channel 4
#define RX_PW_P5        0x16  // Size of receive data in channel 5
#define FIFO_STATUS     0x17  // FIFO Status

//PIPES
#define PIPE_0			0x01
#define PIPE_1 			0x02
#define PIPE_2 			0x04
#define PIPE_3 			0x08
#define PIPE_4 			0x10
#define PIPE_5 			0x20

// define  GPIO for SPI
#define DEFAULT_SPI_Direction 			SPI_Direction_2Lines_FullDuplex
#define DEFAULT_SPI_Mode				SPI_Mode_Master
#define DEFAULT_SPI_DataSize 			SPI_DataSize_8b
#define DEFAULT_SPI_CPOL 				SPI_CPOL_Low
#define DEFAULT_SPI_CPHA 				SPI_CPHA_1Edge
#define DEFAULT_SPI_NSS 				SPI_NSS_Soft
#define DEFAULT_SPI_BaudRatePrescaler	SPI_BaudRatePrescaler_4
#define DEFAULT_SPI_FirstBit 			SPI_FirstBit_MSB
#define DEFAULT_SPI_CRCPolynomial 		7
#define SPI_DELAY 						1


//Struct per la gestione dell'nRF
typedef struct
{
	char* nRF24L01_DeviceName;

	uint16_t CE_Pin;			/* Chip enable pin */
	GPIO_TypeDef* CE_GPIO;
	uint16_t CSN_Pin;			/* Chip enable pin */
	GPIO_TypeDef* CSN_GPIO;

	uint16_t IRQ_Pin;			/* Interrupt pin */
	GPIO_TypeDef* IRQ_GPIO;
	uint8_t IRQ_GPIO_PortSource;
	uint8_t IRQ_GPIO_PinSource;
	uint32_t IRQ_EXTI_Line;

	spi_Device* spi_Device;			/* SPI peripheral to use */
	uint8_t nRF24L01_Freq;
	uint8_t nRF24L01_power_rate;

	//define the initial Address
	uint8_t  TX_ADDRESS[ADR_WIDTH];
	uint8_t  RX_ADDRESS_P0[ADR_WIDTH];
	uint8_t  RX_ADDRESS_P1[ADR_WIDTH];
	uint8_t  RX_ADDRESS_P2;
	uint8_t  RX_ADDRESS_P3;
	uint8_t  RX_ADDRESS_P4;
	uint8_t  RX_ADDRESS_P5;

} nRF24L01_Device;


/*
----------------------------------------------------------------------
---   Layer 1 service - nRF24L01P   ----------------------------------
----------------------------------------------------------------------
*/
void setup_nRF24L01P(uint8_t* myAddress);
void TxMode_nRF24L01P();
void RxMode_nRF24L01P();
void TxFrame_nRF24L01P(uint8_t* pdata, uint8_t length);
void TxBroadcast_nRF24L01P(uint8_t* pdata, uint16_t length);

uint8_t getTxAddress_nRF24L01P();
uint8_t setTxAddress_nRF24L01P(uint8_t*);
uint8_t getPipeAddr_nRF24L01P(uint8_t pipe, uint8_t* addr);
uint8_t setRxAddress_nRF24L01P(uint8_t, uint8_t*);

void resetSoftware_nRF24L01P();
void powerDown_nRF24L01P();

void setTxMutex_nRF24L01P();
void resetTxMutex_nRF24L01P();
uint8_t getTxMutex_nRF24L01P();

void setTxFrameLost_nRF24L01P();
void resetTxFrameLost_nRF24L01P();
uint8_t getTxFrameLost_nRF24L01P();

/*
----------------------------------------------------------------------
---   Layer 1 register - nRF24L01P   ---------------------------------
----------------------------------------------------------------------
*/
void nRF24L01_Delay_us(unsigned long);
uint8_t nRF24L01_set_config(nRF24L01_Device*, uint8_t);

uint8_t nRF24L01_set_auto_ack(nRF24L01_Device*, uint8_t);
uint8_t nRF24L01_noack(nRF24L01_Device* device);

uint8_t nRF24L01_set_enable_pipe(nRF24L01_Device*, uint8_t);
uint8_t nRF24L01_get_enable_pipe();

uint8_t nRF24L01_set_address_width(nRF24L01_Device*, uint8_t);
uint8_t nRF24L01_set_retransmission(nRF24L01_Device*, uint8_t);

uint8_t nRF24L01_set_channel(nRF24L01_Device*, uint8_t);
uint8_t nRF24L01_get_channel();

uint8_t nRF24L01_get_tx_addr(uint8_t* addr);
uint8_t nRF24L01_set_rf(nRF24L01_Device*, uint8_t);
uint8_t nRF24L01_get_status(nRF24L01_Device* device);
uint8_t nRF24L01_set_status(nRF24L01_Device*, uint8_t);
uint8_t nRF24L01_get_fifo_status(nRF24L01_Device*, uint8_t*);
uint8_t nRF24L01_get_payload_length(nRF24L01_Device*, uint8_t*);
uint8_t nRF24L01_flush_rx(nRF24L01_Device* device);
uint8_t nRF24L01_flush_tx(nRF24L01_Device* device);

/*
----------------------------------------------------------------------
---   Layer 1 function - SPI   ---------------------------------------
----------------------------------------------------------------------
*/
void init_nRF24L01(nRF24L01_Device*);
void nRF24L01_CE_L();
void nRF24L01_CE_H();
void nRF24L01_SPI_NSS_L();
void nRF24L01_SPI_NSS_H();

#endif /* NRF24L01_H_ */
